package com.yanqu.road.server.manager.activity.commonteam;

import com.yanqu.road.dao.impl.activity.commonteam.CommonTeamApplyDataDaoImpl;
import com.yanqu.road.dao.impl.activity.commonteam.CommonTeamTeamDataDaoImpl;
import com.yanqu.road.dao.impl.activity.commonteam.CommonTeamUserDataDaoImpl;
import com.yanqu.road.entity.activity.commonteam.data.CommonTeamApplyData;
import com.yanqu.road.entity.activity.commonteam.CommonTeamConfigData;
import com.yanqu.road.entity.activity.commonteam.CommonTeamInitUserData;
import com.yanqu.road.entity.activity.commonteam.data.CommonTeamData;
import com.yanqu.road.entity.activity.commonteam.data.CommonTeamUserData;
import com.yanqu.road.entity.activity.commonteam.enums.CommonTeamLogLeaderOpType;
import com.yanqu.road.entity.activity.commonteam.enums.CommonTeamLogMemberOpType;
import com.yanqu.road.entity.enums.eChatContentType;
import com.yanqu.road.entity.log.cross.commonteam.LogCrossCommonTeamLeaderOp;
import com.yanqu.road.entity.log.cross.commonteam.LogCrossCommonTeamMemberOp;
import com.yanqu.road.entity.player.CrossUserBaseInfo;
import com.yanqu.road.exception.BusinessException;
import com.yanqu.road.logic.helper.ActivityHelper;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.pb.activity.CommonTeamProto;
import com.yanqu.road.pb.player.PlayerProto;
import com.yanqu.road.pb.worldmessage.WorldMessageProto;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.activity.commonteam.pb.CommonTeamPb;
import com.yanqu.road.server.manager.log.CrossAutoLogMgr;
import com.yanqu.road.server.manager.user.CrossUserMgr;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.utils.FixSizeLinkedList;
import com.yanqu.road.utils.ListHelper;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.string.StringUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

public class CommonTeamActivity {

    /**
     *  队伍配置
     */
    private CommonTeamConfigData teamConfig;

    /**
     * 活动分组ID
     */
    private int groupId;

    /**
     * 队伍MAP
     */
    private Map<Integer, CommonTeam> teamMap = new ConcurrentHashMap<>();

    /**
     * 删除的队伍MAP
     */
    private Map<Integer, CommonTeam> delTeamMap = new ConcurrentHashMap<>();

    /**
     * 玩家MAP
     */
    private Map<Long, CommonTeamUserData> userMap = new ConcurrentHashMap<>();

    /**
     * 队伍最大id
     */
    private AtomicInteger maxTeamId = new AtomicInteger(0);

    /**
     * 构造
     * @param teamConfig
     */
    public CommonTeamActivity(CommonTeamConfigData teamConfig, int groupId) {
        this.teamConfig = teamConfig;
        this.groupId = groupId;
        //重载数据
        this.reloadData();
    }

    /**
     * 重载数据
     */
    private void reloadData() {
        int activityId = this.teamConfig.getActivityId();
        int groupId = this.groupId;
        //组队ID
        int maxTeamId = new CommonTeamTeamDataDaoImpl().getCommonMaxTeamId(activityId, groupId);
        this.maxTeamId = new AtomicInteger(maxTeamId);

        //玩家数据
        this.userMap = new CommonTeamUserDataDaoImpl().getCommonTeamUserDataMap(activityId, groupId);
        //构造队伍成员MAP
        Map<Integer, Map<Long, CommonTeamUserData>> teamMemberMap = new ConcurrentHashMap<>();
        for (CommonTeamUserData userData : this.userMap.values()) {
            if (userData.getTeamId() > 0) {
                Map<Long, CommonTeamUserData> memberMap = teamMemberMap.computeIfAbsent(userData.getTeamId(), k -> new ConcurrentHashMap<>());
                memberMap.put(userData.getUserId(), userData);
            }
        }

        //组队数据
        Map<Integer, CommonTeamData> teamDataMap = new CommonTeamTeamDataDaoImpl().getCommonTeamDataMap(activityId, groupId);

        //申请数据
        String teamIds = teamDataMap.keySet().stream().map(String::valueOf).collect(Collectors.joining(","));
        Map<Integer, Map<Long, CommonTeamApplyData>> teamApplyDataMap = new CommonTeamApplyDataDaoImpl().getCommonTeamApplyDataMap(activityId, groupId, teamIds);
        //构造team
        Map<Integer, CommonTeam> teamMap = new ConcurrentHashMap<>();
        for (CommonTeamData teamData : teamDataMap.values()) {
            CommonTeam team = new CommonTeam(teamData);
            //注入成员数据
            Map<Long, CommonTeamUserData> memberMap = teamMemberMap.get(team.getTeamId());
            if (memberMap != null) {
                team.setMemberDataMap(memberMap);
            }
            //注入申请数据
            Map<Long, CommonTeamApplyData> applyMap = teamApplyDataMap.get(team.getTeamId());
            if (applyMap != null) {
                team.setApplyDataMap(applyMap);
            }
            teamMap.put(team.getTeamId(), team);
        }
        this.teamMap = teamMap;
    }

    /**
     * 存储数据
     */
    public void save() {
        //玩家数据
        CommonTeamUserDataDaoImpl userDataDao = new CommonTeamUserDataDaoImpl();
        for (CommonTeamUserData userData : this.userMap.values()) {
            if (userData.isInsertOption()) {
                userDataDao.add(userData);
            } else if (userData.isUpdateOption()) {
                userDataDao.update(userData);
            }
        }
        //队伍数据
        CommonTeamTeamDataDaoImpl teamDataDao = new CommonTeamTeamDataDaoImpl();
        CommonTeamApplyDataDaoImpl applyDataDao = new CommonTeamApplyDataDaoImpl();
        for (CommonTeam team : teamMap.values()) {
            if (team.isInsertOption()) {
                teamDataDao.add(team);
            } else if (team.isUpdateOption()) {
                teamDataDao.update(team);
            }
            //申请数据
            for (CommonTeamApplyData applyData : team.getApplyDataMap().values()) {
                if (applyData.isInsertOption()) {
                    applyDataDao.add(applyData);
                } else if (applyData.isUpdateOption()) {
                    applyDataDao.update(applyData);
                }
            }
            //被删除的申请数据
            List<CommonTeamApplyData> delApplyList;
            synchronized (team.getDelApplyDataMap()) {
                delApplyList = new ArrayList<>(team.getDelApplyDataMap().values());
                team.clearDelApplyDataMap();
            }
            for (CommonTeamApplyData delApply : delApplyList) {
                applyDataDao.update(delApply);
            }
        }
        //被删除的队伍数据的
        List<CommonTeam> delTeamList;
        synchronized (this.delTeamMap) {
            delTeamList = new ArrayList<>(this.delTeamMap.values());
            this.delTeamMap.clear();
        }
        for (CommonTeam delTeam : delTeamList) {
            if (delTeam.isInsertOption()) {
                teamDataDao.add(delTeam);
            } else {
                teamDataDao.update(delTeam);
            }
        }
    }

    /**
     * 刷新配置
     * @param teamConfig
     */
    public void refreshConfig(CommonTeamConfigData teamConfig) {
        this.teamConfig = teamConfig;
    }

    /**
     * 获取配置
     * @return
     */
    public CommonTeamConfigData getConfig() {
        return this.teamConfig;
    }

    /**
     * 获取玩家数据
     * @param userId
     * @return
     */
    public CommonTeamUserData getUserData(long userId) {
        return this.userMap.get(userId);
    }

    /**
     * 获取玩家数据，不存在则创建
     * @param userId
     * @param power
     * @return
     */
    public CommonTeamUserData getUserDataOrCreate(long userId, long power) {
        CommonTeamUserData userData = this.userMap.get(userId);
        if (userData == null) {
            //初始化玩家
            userData = this.initUserData(userId, power);
        } else {
            userData.setScore(power);
        }
        return userData;
    }

    /**
     * 初始化玩家数据
     * @param userId
     * @return
     */
    private synchronized CommonTeamUserData initUserData(long userId, long power) {
        CommonTeamUserData userData = this.userMap.get(userId);
        if (userData == null) {
            //查询下玩家UserBase
            CrossUserBaseInfo crossUserBaseInfo = CrossUserMgr.getCrossUserBaseInfo(userId);
            userData = new CommonTeamUserData(
                    this.teamConfig.getActivityId(),
                    this.groupId,
                    userId,
                    crossUserBaseInfo.getUserBaseInfo().getNickName(),
                    crossUserBaseInfo.getUserBaseInfo().getServerId(),
                    power
            );
            this.userMap.put(userId, userData);
        }
        return userData;
    }

    /**
     * 同步玩家数据
     * @param userId
     */
    public void syncUserData(long userId) {
        CommonTeamUserData userData = this.getUserData(userId);
        if (userData == null) {
            return;
        }
        CommonTeamProto.CommonTeamGetUserDataRespMsg.Builder msg = CommonTeamProto.CommonTeamGetUserDataRespMsg.newBuilder();
        msg.setRet(0);
        msg.setActivityId(this.teamConfig.getActivityId());
        msg.setUserData(CommonTeamPb.buildCommonTeamUserData(userData));
        if (userData.getTeamId() > 0) {
            CommonTeam team = this.getTeam(userData.getTeamId());
            if (team != null) {
                //是否带上申请数据，队长才需要该数据
                boolean showApplyData = false;
                if (team.getLeaderId() == userId) {
                    showApplyData = true;
                }
                msg.setTeam(CommonTeamPb.buildCommonTeamData(team, true, showApplyData));
            }
        }
        YanQuMessage message = YanQuMessageUtils.buildMessage(ClientProtocol.U_COMMON_TEAM_GET_USER_DATA, msg);
        MessageHelper.sendPacket(userData.getServerId(), userId, message);
    }

    /**
     * 广播给队长
     * @param leaderUserData
     * @param type
     * @param userData
     */
    public void syncLeaderMsg(CommonTeamUserData leaderUserData, int type, CommonTeamUserData userData) {
        CommonTeamProto.CommonTeamLeaderSync.Builder msg = CommonTeamProto.CommonTeamLeaderSync.newBuilder();
        msg.setActivityId(this.teamConfig.getActivityId());
        msg.setType(type);
        msg.setUserData(CommonTeamPb.buildCommonTeamUserData(userData));
        YanQuMessage message = YanQuMessageUtils.buildMessage(ClientProtocol.U_COMMON_TEAM_LEADER_SYNC, msg);
        MessageHelper.sendPacket(leaderUserData.getServerId(), leaderUserData.getUserId(), message);
    }

    /**
     * 广播给队员
     * @param leaderUserData
     * @param type
     * @param team
     */
    public void syncMemberMsg(CommonTeamUserData leaderUserData, int type, CommonTeam team) {
        CommonTeamProto.CommonTeamMemberSync.Builder msg = CommonTeamProto.CommonTeamMemberSync.newBuilder();
        msg.setActivityId(this.teamConfig.getActivityId());
        msg.setType(type);
        msg.setTeam(CommonTeamPb.buildCommonTeamData(team, true, false));
        YanQuMessage message = YanQuMessageUtils.buildMessage(ClientProtocol.U_COMMON_TEAM_MEMBER_SYNC, msg);
        MessageHelper.sendPacket(leaderUserData.getServerId(), leaderUserData.getUserId(), message);
    }

    /**
     * 判断是否在组队期
     * @return
     */
    public boolean checkInTeamTime() {
        long now = System.currentTimeMillis();
        if (now >= this.teamConfig.getActivityInfo().getBeginTime() && now <= this.teamConfig.getEndTime()) {
            return true;
        }
        return false;
    }

    /**
     * 删除队伍
     * @param team
     */
    private synchronized void removeTeam(CommonTeam team) {
        team.setDelFlag(1);
        this.teamMap.remove(team.getTeamId());
        this.delTeamMap.put(team.getTeamId(), team);
    }

    /**
     * 判断是否入队CD
     * @param selfLeaveTeamTime 主动离队时间
     * @return
     */
    private boolean checkTeamJoinTeamCd(long selfLeaveTeamTime) {
        long endJoinTime = selfLeaveTeamTime + this.teamConfig.getJoinCd() * 1000L;
        if (endJoinTime >= System.currentTimeMillis()) {
            return true;
        }
        return false;
    }

    /**
     * 判断队伍名称是否存在
     * @param teamName
     * @return
     */
    private boolean checkTeamNameExist(String teamName) {
        for (CommonTeam commonTeam : teamMap.values()) {
            if (commonTeam.getTeamName().equals(teamName)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取玩家申请数据
     * @param userId
     * @return
     */
    private int getUserApplyNum(long userId) {
        int num = 0;
        for (CommonTeam team : this.teamMap.values()) {
            CommonTeamApplyData applyData = team.getApplyData(userId);
            if (applyData != null) {
                num++;
            }
        }
        return num;
    }

    /**
     * 删除玩家所有申请数据
     */
    public void removeUserApply(long userId) {
        for (CommonTeam team : this.teamMap.values()) {
            if (team.checkInApply(userId)) {
                team.removeApplyData(userId);
            }
        }
    }

    /**
     * 获取队伍创建费用
     * @return
     */
    public String getCreateTeamCost() {
        return this.teamConfig.getCreateTeamCost();
    }

    /**
     * 获取队伍信息，根据玩家ID
     * @param userId
     * @return
     * @throws BusinessException
     */
    public CommonTeam getTeamByUserId(long userId) throws BusinessException {
        //判断玩家是否存在
        CommonTeamUserData userData = this.getUserData(userId);
        if (userData == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_USER_NOT_EXIST);
        }
        //判断队伍是否存在
        CommonTeam team = this.getTeam(userData.getTeamId());
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_NOT_EXIST);
        }
        return team;
    }

    /**********************************************************榜单相关**************************************/

    /**
     * 队伍榜单分数变更
     * @param teamId
     * @param conditionType
     * @param rankScore
     */
    public void changeTeamRankScore(int teamId, int conditionType, long rankScore, long param) {
        CommonTeam team = this.getTeam(teamId);
        if (team != null) {
            team.putRankScore(conditionType, rankScore, param);
        }
    }

    /**
     * 获取队伍榜单
     * @return
     */
    public List<CommonTeam> getTeamRankList(int conditionType) {
        List<CommonTeam> list = new ArrayList<>(this.teamMap.values());
        //过滤掉分数为0的
        list.removeIf(team -> team.getRankScore(conditionType) == 0);
        //排序,先按param降序，再按score降序
        list.sort(Comparator.comparingLong((CommonTeam team) -> team.getRankScoreParam(conditionType)).reversed().
                thenComparing(Comparator.comparingLong((CommonTeam team) -> team.getRankScore(conditionType)).reversed()));
        return list;
    }

    /**
     * 获取排名
     * @param teamId
     * @return
     */
    public int getTeamRank(int teamId, int conditionType) {
        int rank = -1;
        List<CommonTeam> list = this.getTeamRankList(conditionType);
        for (int i = 0; i < list.size(); i++) {
            CommonTeam team = list.get(i);
            if (team.getTeamId() == teamId) {
                rank = i + 1;
                break;
            }
        }
        return rank;
    }

    /**
     * 获取排名，根据玩家id
     * @param userId
     * @param conditionType
     * @return
     * @throws BusinessException
     */
    public int getTeamRankByUserId(long userId, int conditionType) throws BusinessException {
        CommonTeam team = this.getTeamByUserId(userId);
        return this.getTeamRank(team.getTeamId(), conditionType);
    }


    /***********************************************************交互协议***********************************/

    /**
     * 创建队伍
     * @param userId
     * @param teamName
     * @throws BusinessException
     */
    public synchronized CommonTeam createTeam(long userId, String teamName, boolean enoughCost) throws BusinessException {
        //判断是否活动进行中
        if (!ActivityHelper.activityInTime(this.teamConfig.getActivityInfo())) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_NOT_IN_ACTIVITY_TIME);
        }
        //校验队伍名称是否被使用
        if (this.checkTeamNameExist(teamName)) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_NAME_EXIST);
        }
        //校验队伍名称长度
        if (StringUtils.isNullOrEmpty(teamName) || teamName.length() > this.teamConfig.getNameLengthMax()) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_NAME_ERROR);
        }
        //判断玩家是否存在
        CommonTeamUserData userData = this.getUserData(userId);
        if (userData == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_USER_NOT_EXIST);
        }
        //判断玩家是否已经在队伍中
        if (userData.getTeamId() > 0) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_USER_ALREADY_IN_TEAM);
        }
        //是否入队cd中
        if (this.checkTeamJoinTeamCd(userData.getSelfLeaveTeamTime())) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_JOIN_CD);
        }
        //判断是否需要消耗
        if (userData.getLastCreateTeamTime() > 0 && !enoughCost) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_CREATE_TEAM_COST_NOT_ENOUGH);
        }
        //创建队伍
        CommonTeam team = new CommonTeam (
                this.teamConfig.getActivityId(),
                this.groupId,
                userData.getServerId(),
                this.maxTeamId.incrementAndGet(),
                teamName,
                userData.getUserId(),
                userData.getUserName(),
                userData.getScore()
        );
        this.teamMap.put(team.getTeamId(), team);
        //添加成员
        team.addMemberData(userData);
        //创建队伍时间
        userData.setLastCreateTeamTime(System.currentTimeMillis());
        //删除玩家所有申请
        this.removeUserApply(userId);
        CommonTeamMgr.createTeamAfterHandle(this.teamConfig.getActivityId(), this.groupId, team.getTeamId(), userData);
        //聊天信息同步-创建队伍
        CommonTeamProto.CommonTeamChatMsg.Builder chatMsgBuilder = this.createTeamChatMsg(userId, CommonTeamProto.CommonTeamChatTypeEnum.CREATE_TEAM_VALUE, eChatContentType.Common.getContentType(), null);
        team.sendTeamChatMsg(chatMsgBuilder.build());
        return team;
    }

    /**
     * 获取队伍列表
     * @param pageNum
     * @param serverId
     * @param sameServerFlag
     * @param hideFullTeamFlag 是否过滤已满队伍
     * @return
     */
    public List<CommonTeam> getTeamList(long userId, int pageNum, long serverId, boolean sameServerFlag, boolean hideFullTeamFlag) {
        int pageSize = 20;
        List<CommonTeam> list = new ArrayList<>(this.teamMap.values());
        //过滤
        List<CommonTeam> filteredList = list.stream()
                .filter(team -> !sameServerFlag || team.getServerId() == serverId)
                .filter(team -> !hideFullTeamFlag || team.getMemberDataMap().size() < this.teamConfig.getUserNumMax())
                .collect(Collectors.toList());
        //按实力倒序排序一下，再按玩家的申请队伍排序一下
        filteredList.sort(Comparator.comparingLong(CommonTeam::getScore).reversed().thenComparing(team -> team.checkInApply(userId)));
        //分页
        return ListHelper.paginate(filteredList, pageSize, pageNum);
    }

    /**
     * 获取队伍详情
     * @param teamId
     * @return
     */
    public CommonTeam getTeam(int teamId) {
        return this.teamMap.get(teamId);
    }

    /**
     * 获取队伍MAO
     * @return
     */
    public Map<Integer, CommonTeam> getTeamMap() {
        return this.teamMap;
    }

    /**
     * 获取申请MAP
     * @param userId
     * @return
     * @throws BusinessException
     */
    public Map<Long, CommonTeamApplyData> getApplyMap(long userId) throws BusinessException {
        //判断玩家是否存在
        CommonTeamUserData userData = this.getUserData(userId);
        if (userData == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_USER_NOT_EXIST);
        }
        //判断队伍是否存在
        CommonTeam team = this.getTeam(userData.getTeamId());
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_NOT_EXIST);
        }
        return team.getApplyDataMap();
    }

    /**
     * 申请入队
     * @param userId
     * @param teamId
     * @throws BusinessException
     */
    public synchronized void applyJoinTeam(long userId, int teamId) throws BusinessException {
        //判断是否活动进行中
        if (!ActivityHelper.activityInTime(this.teamConfig.getActivityInfo())) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_NOT_IN_ACTIVITY_TIME);
        }
        //判断玩家是否存在
        CommonTeamUserData userData = this.getUserData(userId);
        if (userData == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_USER_NOT_EXIST);
        }
        //判断玩家是否已经入队
        if (userData.getTeamId() > 0) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_USER_ALREADY_IN_TEAM);
        }
        //判断玩家申请达到上限
        if (this.getUserApplyNum(userId) >= this.teamConfig.getUserApplyMax()) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_USER_APPLY_FULL);
        }
        //判断队伍是否存在
        CommonTeam team = this.getTeam(teamId);
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_NOT_EXIST);
        }
        //判断队伍申请达到上限
        if (team.getMemberDataMap().size() >= teamConfig.getUserNumMax()) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_FULL_MEMBER);
        }
        //判断队伍申请上限
        if (team.getApplyDataMap().size() >= this.teamConfig.getApplyMax()) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_APPLY_USER_FULL);
        }
        //判断是否已经申请过该队伍
        if (team.checkInApply(userId)) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_ALREADY_IN_TEAM_APPLY);
        }
        //是否入队cd中
        if (this.checkTeamJoinTeamCd(userData.getSelfLeaveTeamTime())) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_JOIN_CD);
        }
        //强制
        boolean supportCross = getConfig().getJoinCrossTeamFlag() == 1;
        if(!supportCross && userData.getServerId() != team.getServerId()){
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_ACTIVITY_JOIN_CROSS_SERVER_LIMIT);
        }
        //添加申请
        team.addApplyData(userData, this.teamConfig);
        //广播给队长
        this.syncLeaderMsg(team.getLeaderUserData(), CommonTeamProto.CommonTeamLeaderSyncTypeEnum.LEADER_SYNC_APPLY_VALUE, userData);
    }

    /**
     * 撤销入队申请
     * @param userId
     * @param teamId
     * @throws BusinessException
     */
    public synchronized void cancelJoinTeam(long userId, int teamId) throws BusinessException {
        //判断是否活动进行中
        if (!ActivityHelper.activityInTime(this.teamConfig.getActivityInfo())) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_NOT_IN_ACTIVITY_TIME);
        }
        //判断玩家是否存在
        CommonTeamUserData userData = this.getUserData(userId);
        if (userData == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_USER_NOT_EXIST);
        }
        //判断队伍是否存在
        CommonTeam team = this.getTeam(teamId);
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_NOT_EXIST);
        }
        //移除申请
        team.removeApplyData(userId);
        //广播给队长
        this.syncLeaderMsg(team.getLeaderUserData(), CommonTeamProto.CommonTeamLeaderSyncTypeEnum.LEADER_SYNC_CANCEL_APPLY_VALUE, userData);
    }

    /**
     * 退出队伍
     * @param userId
     * @throws BusinessException
     */
    public synchronized void quitTeam(long userId) throws BusinessException {
        //判断是否在组队期内
        if (!this.checkInTeamTime()) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_NOT_IN_TEAM_TIME);
        }
        //判断玩家是否存在
        CommonTeamUserData userData = this.getUserData(userId);
        if (userData == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_USER_NOT_EXIST);
        }
        //判断队伍是否存在
        CommonTeam team = this.getTeam(userData.getTeamId());
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_NOT_EXIST);
        }
        if (team.getLeaderId() == userData.getUserId()) {
            //队长退出队伍
            //队伍不能先移除
            //team.quitTeam(userData);
            //解散队伍，移除所有成员
            Iterator<Map.Entry<Long, CommonTeamUserData>> attIt = team.getMemberDataMap().entrySet().iterator();
            while (attIt.hasNext()) {
                Map.Entry<Long, CommonTeamUserData> entry = attIt.next();
                CommonTeamUserData member = entry.getValue();
                //队员退出队伍
                team.quitTeam(member);
                //队员广播：解散队伍
                this.syncMemberMsg(member, CommonTeamProto.CommonTeamMemberSyncTypeEnum.MEMBER_SYNC_TEAM_OUT_VALUE, team);
                CommonTeamMgr.quitTeamAfterHandle(this.teamConfig.getActivityId(), this.groupId, team.getTeamId(), member);
            }
            //删除队伍
            this.removeTeam(team);
        } else {
            //队员退出队伍
            team.quitTeam(userData);
            //广播队友，有玩家退出
            for (CommonTeamUserData member : team.getMemberDataMap().values()) {
                //同步玩家数据
                this.syncUserData(member.getUserId());
            }
            CommonTeamMgr.quitTeamAfterHandle(this.teamConfig.getActivityId(), this.groupId, team.getTeamId(), userData);
        }
        //设置主动离队时间
        userData.setSelfLeaveTeamTime(System.currentTimeMillis());
        //聊天信息同步-退出队伍
        CommonTeamProto.CommonTeamChatMsg.Builder chatMsgBuilder = this.createTeamChatMsg(userId, CommonTeamProto.CommonTeamChatTypeEnum.LEAVE_TEAM_VALUE, eChatContentType.Common.getContentType(), null);
        team.sendTeamChatMsg(chatMsgBuilder.build());
        //日志
        LogCrossCommonTeamMemberOp log = new LogCrossCommonTeamMemberOp(
                this.teamConfig.getActivityId(),
                this.groupId,
                userId,
                team.getTeamId(),
                CommonTeamLogMemberOpType.LEAVE.getType()
        );
        CrossAutoLogMgr.add(log);
    }

    /**
     * 踢出成员
     * @param userId
     * @param memberId
     * @throws BusinessException
     */
    public synchronized void kickMember(long userId, long memberId) throws BusinessException {
        //判断是否在组队期内
        if (!this.checkInTeamTime()) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_NOT_IN_TEAM_TIME);
        }
        //判断玩家是否存在
        CommonTeamUserData userData = this.getUserData(userId);
        if (userData == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_USER_NOT_EXIST);
        }
        //判断被踢出的成员是否存在
        CommonTeamUserData kickUser = this.getUserData(memberId);
        if (kickUser == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_USER_NOT_EXIST);
        }
        //判断队伍是否存在
        CommonTeam team = this.getTeam(userData.getTeamId());
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_NOT_EXIST);
        }
        //队长才能操作
        if (userId != team.getLeaderId()) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_KICK_NOT_LEADER);
        }
        if (memberId == userId) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_KICK_NOT_SELF);
        }
        //踢出操作
        team.quitTeam(kickUser);
        //广播给被踢出的队员
        this.syncMemberMsg(kickUser, CommonTeamProto.CommonTeamMemberSyncTypeEnum.MEMBER_SYNC_KICK_OUT_VALUE, team);
        //广播给其他队友，有玩家退出
        for (CommonTeamUserData member : team.getMemberDataMap().values()) {
            //同步玩家数据
            this.syncUserData(member.getUserId());
        }
        //聊天信息同步-退出队伍
        CommonTeamProto.CommonTeamChatMsg.Builder chatMsgBuilder = this.createTeamChatMsg(memberId, CommonTeamProto.CommonTeamChatTypeEnum.LEAVE_TEAM_VALUE, eChatContentType.Common.getContentType(), null);
        team.sendTeamChatMsg(chatMsgBuilder.build());
        CommonTeamMgr.quitTeamAfterHandle(this.teamConfig.getActivityId(), this.groupId, team.getTeamId(), kickUser);
        //日志
        LogCrossCommonTeamLeaderOp log = new LogCrossCommonTeamLeaderOp(
                this.teamConfig.getActivityId(),
                this.groupId,
                userId,
                team.getTeamId(),
                CommonTeamLogLeaderOpType.KICK.getType(),
                memberId
        );
        CrossAutoLogMgr.add(log);
    }

    /**
     * 同意入队
     * @param userId
     * @param agreeUserId
     * @throws BusinessException
     */
    public synchronized void agreeJoinTeam(long userId, long agreeUserId, String language) throws BusinessException {
        //判断是否活动进行中
        if (!ActivityHelper.activityInTime(this.teamConfig.getActivityInfo())) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_NOT_IN_ACTIVITY_TIME);
        }
        //判断玩家是否存在
        CommonTeamUserData userData = this.getUserData(userId);
        if (userData == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_USER_NOT_EXIST);
        }
        //判断队伍是否存在
        CommonTeam team = this.getTeam(userData.getTeamId());
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_NOT_EXIST);
        }
        //判断玩家是否存在
        CommonTeamUserData agreeUser = this.getUserData(agreeUserId);
        if (agreeUser == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_USER_NOT_EXIST);
        }
        //判断对方是否已经在队伍内
        if (agreeUser.getTeamId() > 0) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_USER_ALREADY_IN_TEAM);
        }
        //判断队伍成员上限
        if (team.getMemberDataMap().size() >= this.teamConfig.getUserNumMax()) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_FULL_MEMBER);
        }
        //判断申请是否存在
        CommonTeamApplyData applyData = team.getApplyData(agreeUserId);
        if (applyData == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_APPLY_NOT_EXIST);
        }
        //加入队伍
        team.addMemberData(agreeUser);
        //删除玩家所有申请
        this.removeUserApply(agreeUserId);
        //入队成功，不同活动的处理策略
        CommonTeamMgr.agreeJoinTeamAfterHandle(this.teamConfig.getActivityId(), this.groupId, team.getTeamId(), agreeUser, language);
        //广播给玩家，入队成功
        this.syncMemberMsg(agreeUser, CommonTeamProto.CommonTeamMemberSyncTypeEnum.MEMBER_SYNC_JOIN_TEAM_VALUE, team);
        //广播给其他队友，队伍数据变更
        for (CommonTeamUserData member : team.getMemberDataMap().values()) {
            //同步玩家数据
            this.syncUserData(member.getUserId());
        }
        //聊天信息同步-加入队伍
        CommonTeamProto.CommonTeamChatMsg.Builder chatMsgBuilder = this.createTeamChatMsg(agreeUserId, CommonTeamProto.CommonTeamChatTypeEnum.JOIN_TEAM_VALUE, eChatContentType.Common.getContentType(), null);
        team.sendTeamChatMsg(chatMsgBuilder.build());
        //日志
        LogCrossCommonTeamLeaderOp log = new LogCrossCommonTeamLeaderOp(
                this.teamConfig.getActivityId(),
                this.groupId,
                userId,
                team.getTeamId(),
                CommonTeamLogLeaderOpType.AGREE.getType(),
                agreeUserId
        );
        CrossAutoLogMgr.add(log);
    }

    /**
     * 一键拒绝入队
     * @param userId
     * @throws BusinessException
     */
    public synchronized void oneKeyRejectJoinTeam(long userId) throws BusinessException {
        //判断是否活动进行中
        if (!ActivityHelper.activityInTime(this.teamConfig.getActivityInfo())) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_NOT_IN_ACTIVITY_TIME);
        }
        //判断玩家是否存在
        CommonTeamUserData userData = this.getUserData(userId);
        if (userData == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_USER_NOT_EXIST);
        }
        //判断队伍是否存在
        CommonTeam team = this.getTeam(userData.getTeamId());
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_NOT_EXIST);
        }
        team.oneKeyRejectJoinTeam();
    }

    /**
     * 发送普通聊天信息
     * @param userId
     * @param chatMsg
     * @throws BusinessException
     */
    public void sendTeamChatMsg(long userId, WorldMessageProto.WorldMessageTempMsg chatMsg) throws BusinessException {
        //判断是否活动进行中-展示期
        if (!ActivityHelper.activityInShowTime(this.teamConfig.getActivityInfo())) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_NOT_IN_ACTIVITY_SHOW_TIME);
        }
        //判断玩家是否存在
        CommonTeamUserData userData = this.getUserData(userId);
        if (userData == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_USER_NOT_EXIST);
        }
        //判断队伍是否存在
        CommonTeam team = this.getTeam(userData.getTeamId());
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_NOT_EXIST);
        }
        //发送普通聊天信息
        CommonTeamProto.CommonTeamChatMsg.Builder chatMsgBuilder = this.createTeamChatMsg(userId, CommonTeamProto.CommonTeamChatTypeEnum.NORMAL_VALUE, chatMsg.getContentType(), chatMsg.getContent());
        team.sendTeamChatMsg(chatMsgBuilder.build());
    }

    /**
     * 创建聊天消息体
     * @param userId
     * @param type
     * @param contentType
     * @param content
     * @return
     */
    public CommonTeamProto.CommonTeamChatMsg.Builder createTeamChatMsg(long userId, int type, int contentType, String content) {
        CommonTeamProto.CommonTeamChatMsg.Builder chatMsgBuilder = CommonTeamProto.CommonTeamChatMsg.newBuilder();
        //通用消息模版
        WorldMessageProto.WorldMessageTempMsg.Builder messageTempMsg = WorldMessageProto.WorldMessageTempMsg.newBuilder();
        messageTempMsg.setType(type);
        messageTempMsg.setContentType(contentType);
        messageTempMsg.setUserId(userId);
        messageTempMsg.setContent(content == null ? "" : content);
        messageTempMsg.setSendTime(System.currentTimeMillis() / 1000);
        CrossUserBaseInfo userBaseInfo = CrossUserMgr.getCrossUserBaseInfo(userId);
        if (userBaseInfo != null && userBaseInfo.getUserBaseInfo() != null) {
            PlayerProto.PlayerBaseTempMsg.Builder baseMsg = PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo.getUserBaseInfo());
            messageTempMsg.setPlayerBaseData(baseMsg);
        }
        chatMsgBuilder.setMsg(messageTempMsg);
        return chatMsgBuilder;
    }

    /**
     * 获取队伍聊天信息LIST
     * @param userId
     * @return
     * @throws BusinessException
     */
    public FixSizeLinkedList<CommonTeamProto.CommonTeamChatMsg> getTeamChatMsgList(long userId) throws BusinessException {
        //判断是否活动进行中-展示期
        if (!ActivityHelper.activityInShowTime(this.teamConfig.getActivityInfo())) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_NOT_IN_ACTIVITY_SHOW_TIME);
        }
        //判断玩家是否存在
        CommonTeamUserData userData = this.getUserData(userId);
        if (userData == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_USER_NOT_EXIST);
        }
        //判断队伍是否存在
        CommonTeam team = this.getTeam(userData.getTeamId());
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_COMMON_TEAM_TEAM_NOT_EXIST);
        }
        //获取队伍聊天信息
        return team.getTeamChatMsgList();
    }
}
